package com.ruoyi.account.service;

import com.ruoyi.account.domain.DebtVO;
import com.ruoyi.account.domain.Expense;
import com.ruoyi.account.mapper.ExpenseMapper;
import com.ruoyi.account.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DebtService {

    @Autowired
    private ExpenseMapper expenseMapper;
    @Autowired
    private UserMapper userMapper;

    /**
     * 计算账本中成员间的债务关系
     */
    @Transactional(readOnly = true)
    public List<DebtVO> calculateDebts(Long ledgerId) {
        // 1. 获取所有支出记录
        Expense expense1 = new Expense();
        expense1.setLedgerId(ledgerId);
        List<Expense> expenses = expenseMapper.selectExpenseList(expense1);

        // 2. 初始化净余额Map（key=用户ID, value=净支出）
        Map<Long, BigDecimal> netMap = new HashMap<>();
        expenses.forEach(expense -> {
            // 支付人支出增加
            netMap.merge(expense.getPayerId(), expense.getAmount(), BigDecimal::add);
            // 参与人支出减少（平均分摊）
            BigDecimal share = expense.getAmount()
                .divide(new BigDecimal(expense.getParticipantIds().split(",").length), 2, RoundingMode.HALF_UP);
            Arrays.stream(expense.getParticipantIds().split(","))
                .map(Long::parseLong)
                .forEach(pid -> netMap.merge(pid, share.negate(), BigDecimal::add));
        });

        // 3. 分离债权人和债务人
        List<Map.Entry<Long, BigDecimal>> creditors = netMap.entrySet().stream()
            .filter(e -> e.getValue().compareTo(BigDecimal.ZERO) > 0)
            .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
            .collect(Collectors.toList());

        List<Map.Entry<Long, BigDecimal>> debtors = netMap.entrySet().stream()
            .filter(e -> e.getValue().compareTo(BigDecimal.ZERO) < 0)
            .sorted((a, b) -> a.getValue().compareTo(b.getValue()))
            .collect(Collectors.toList());

        // 4. 双指针算法匹配债务
        List<DebtVO> debts = new ArrayList<>();
        int i = 0, j = 0;
        while (i < creditors.size() && j < debtors.size()) {
            Map.Entry<Long, BigDecimal> cred = creditors.get(i);
            Map.Entry<Long, BigDecimal> debt = debtors.get(j);

            BigDecimal settleAmount = cred.getValue().min(debt.getValue().abs());
            debts.add(new DebtVO(
                debt.getKey(),
                getUserName(debt.getKey()),
                cred.getKey(),
                getUserName(cred.getKey()),
                settleAmount
            ));

            // 更新剩余金额
            cred.setValue(cred.getValue().subtract(settleAmount));
            debt.setValue(debt.getValue().add(settleAmount));

            if (cred.getValue().compareTo(BigDecimal.ZERO) == 0) i++;
            if (debt.getValue().compareTo(BigDecimal.ZERO) == 0) j++;
        }

        return debts;
    }

    private String getUserName(Long userId) {
        return userMapper.selectById(userId).getName();
    }
}